import pygame
from pygame import *
from random import randint as random
from math import sin, cos, radians, atan2, hypot
from sys import exit
from os.path import join

from audio       import *
from map_def     import *
from simple_math import *
from input       import *
from mage        import *
from ui          import *
from options     import *
from game_menus  import *

#def get_input():
#    global players, joysticks
#    event.clear([MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN, JOYAXISMOTION,
#                 JOYBALLMOTION, JOYHATMOTION])
#
#    events = event.get([KEYUP])
#    if events != []:
#        exit(0)
#
#    events = event.get(JOYBUTTONDOWN)
#    for e in events:
#        players[e.joy].press(e.button)
#    events = event.get(JOYBUTTONUP)
#    for e in events:
#        players[e.joy].release(e.button)        

def set_graphics():
    global screen_size, screen
    pygame.init()

    screen_size = (800, 600)
    display.set_mode(screen_size)

#    modes       = display.list_modes()
#    screen      = display.set_mode(modes[2])
#    screen_size = display.get_surface().get_size()
    mouse.set_visible(False)


        
#def respawn(player, map):
#    player.position = (random(100,1000), random(100, 800))
#    player.needs_respawn = False

def game_over(mages):
    return len([m for m in mages if m.hit_points > 0]) > 1

def mages_alive(mages):
    return len([m for m in mages if m.hit_points > 0])

def quit():
    exit(0)

def display_winner(mages):
    screen = display.get_surface()
    mages_left = [m for m in mages if m.hit_points > 0]
    if len(mages_left) > 0:
        message = "Player %d is victorious!" %(mages_left[0].mage_id+1)
    else:
        message = "All players were defeated!"

    clock = time.Clock()
    endgame_cooldown = ENDGAME_COOLDOWN

    std_font = font.Font(join("data", "fonts", "DejaVuSerif.ttf"), 12)

    banner_rect        = rect.Rect(0, 0, banner_w, banner_h)
    banner_rect.center = (screen.get_width()/2, screen.get_height()/2)
    pattern_fill(patterns['gray'], screen, banner_rect)
    draw.rect(screen, WHITE, banner_rect, 1)
    text = std_font.render(message, False, WHITE)
    text_rect = text.get_rect(center=(screen.get_width()/2, screen.get_height()/2))
    screen.blit(text, text_rect)
    display.update()

    while not event.get(QUIT) and endgame_cooldown:
        endgame_cooldown -= 1
        event.clear([KEYDOWN, JOYBUTTONDOWN, MOUSEMOTION, MOUSEBUTTONUP,
            MOUSEBUTTONDOWN, JOYAXISMOTION, JOYBALLMOTION, JOYHATMOTION,
            JOYBUTTONUP, KEYUP])
        if event.get(VIDEOEXPOSE):
            display.update()
        clock.tick(60)
        
def main_loop():
    screen = display.get_surface()

    m = Map(join("data", "maps", option["map"]))
    m.draw(screen)

    effects     = []
    projectiles = []
    mages       = []

    endgame_cooldown = ENDGAME_COOLDOWN

    #Assign inputs to the 4 mages:
    game_inputs = []
    if option['inputs'][0] is not None:
        mage = Mage((0, 255, 0), (150, 100), 0)
        mages.append(mage)
        i = inputs[option['inputs'][0]]
        i.assign_mage(mage)
        game_inputs.append(i)
    if option['inputs'][1] is not None:
        mage = Mage((255, 0, 255), (650, 500), 1)
        mages.append(mage)
        i = inputs[option['inputs'][1]]
        i.assign_mage(mage)
        game_inputs.append(i)
    if option['inputs'][2] is not None:
        mage = Mage((0, 255, 255), (150, 500), 2)
        mages.append(mage)
        i = inputs[option['inputs'][2]]
        i.assign_mage(mage)
        game_inputs.append(i)
    if option['inputs'][3] is not None:
        mage = Mage((255, 0, 0), (650, 100), 3)
        mages.append(mage)
        i = inputs[option['inputs'][3]]
        i.assign_mage(mage)
        game_inputs.append(i)

    # Do not start game if we do not have enough mages. Ugly hack. D=
    if len(mages) < 2:
        return

    clock = time.Clock()
    id = 0
    event.post(event.Event(VIDEOEXPOSE))
    while mages_alive(mages) > 1 or endgame_cooldown > 0:
        event.clear([MOUSEMOTION, MOUSEBUTTONUP, MOUSEBUTTONDOWN, JOYAXISMOTION,
                     JOYBALLMOTION, JOYHATMOTION, JOYBUTTONUP, KEYUP])

        ##########################
        if event.get(QUIT):
            return
        ##########################

        if mages_alive(mages) <= 1:
            endgame_cooldown-=1

        joypresses = event.get(JOYBUTTONDOWN)
        keypresses = event.get(KEYDOWN)

        #Pega os retangulos iniciais de tudo
        dirty_rects = []
        for thing in mages+projectiles+effects:
            dirty_rects.append(thing.get_rect())

        #Interacao dos magos
        for i in game_inputs:
            #Pega input dos dos jogadores
            if i.input_type == JOYSTICK:
                actions = i.get_actions(joypresses)
            elif i.input_type == KEYBOARD:
                actions = i.get_actions(keypresses)
            if SCREENSHOT in actions:
                image.save(display.get_surface(), "Screenshot"+str(id)+".bmp")
                id += 1
            (xspeed, yspeed) = i.get_axes()

            #Define proximo estado dos magos
            i.mage.turn(xspeed, yspeed)
            pos = i.mage.get_next_position(xspeed, yspeed)
            
            #Verifica colisao com PAREDES
            for wall in m.walls + [m.external_wall]:
                for (A, B) in wall.lines:
                    distance = line_segment_point_distance(A, B, pos)
                    if distance < MAGE_RADIUS:
                        pos = push_back(A, B, pos, MAGE_RADIUS-distance)
            
            #Coloca o mago na posicao adequada
            i.mage.move(pos)
            i.mage.act(actions, projectiles, effects, mages)
        
        #Interacao dos projeteis
        for p in projectiles:
            pos = p.get_next_position()
            collision_distance = None
            collision_wall     = None
            collision_mages    = []

            #Verificando colisao com paredes
            for wall in m.walls + [m.external_wall]:
                for(A, B) in wall.lines:
                    distance = line_segment_point_distance(A, B, pos)
                    if distance < p.radius:
                        if collision_distance:
                            if distance < collision_distance:
                                collision_distance = distance
                                collision_wall = (A, B)
                        else:
                            collision_distance = distance
                            collision_wall = (A, B)

            #Verificando colisao com magos
            for mage in mages:
                distance = point_point_distance(pos, mage.position)
                if distance < p.radius + MAGE_RADIUS:
                    collision_distance = distance
                    collision_mages.append(mage)

            #Desfecho da colisao
            if collision_distance:
                effect = p.effect_class(p.position)
                play_sound(effect.sound)
                projectiles.extend(p.burst())
                if effect:
                    effects.append(effect)
                if collision_wall:
                    p.hit_wall(collision_wall[0], collision_wall[1])
                for mage in collision_mages:
                    p.hit_mage(mage)
                #Codigo para identificar o ponto exato da colisao esta bugado. =(
                #pos = p.hit_wall_pos(collision_wall[0], collision_wall[1], collision_distance) 
                pos = p.position
            
            p.move(pos)
            dirty_rects.append(m.burn(p.position, 20))
        
        # Mark bigger burn spots for projectiles that have just been destroyed
        burn_spots = [p for p in projectiles if p.destroy == True]
        for b in burn_spots:
            dirty_rects.append(m.burn(b.position, 200))

        # remove the projectiles that are done bouncing around or exploded
        projectiles = [p for p in projectiles if p.destroy == False]
        
        for effect in effects:
            effect.update()
        effects = [e for e in effects if e.destroy == False]

        ###################
        # Draw everything #
        ###################
        m.draw(screen)

        for drawable in projectiles+mages+effects:
            drawable.draw(screen)
            dirty_rects.append(drawable.get_rect())

        if event.get(VIDEOEXPOSE):
            display.update()
        else:
            display.update(dirty_rects)
        clock.tick(60)

    #If I reach here, the game ended and we may have a winner to announce.
    display_winner(mages)

def main():
    options_init()
    set_graphics()
    event.clear()
    play_music(join("data", "music", "Electric Funky - Blondie.ogg"))
    input_init()
    ui_init()
    map_def_init()
    main_menu()

